library(sf)
Linking to GEOS 3.4.2, GDAL 2.1.2, proj.4 4.9.1
library(ggplot2) #development version!
## devtools::install_github("tidyverse/ggplot2")
library(tidyverse)
Loading tidyverse: tibble
Loading tidyverse: tidyr
Loading tidyverse: readr
Loading tidyverse: purrr
Loading tidyverse: dplyr
Conflicts with tidy packages --------------------------------------------------------
filter(): dplyr, stats
lag():    dplyr, stats
library(readr)
## Not sure about this bit
#library("tidyverse",lib.loc="/Library/Frameworks/R.framework/Versions/3.4/Resources/library")
library(cowplot)

Attaching package: ‘cowplot’

The following object is masked from ‘package:ggplot2’:

    ggsave
library(sp)
library(gridExtra)

Attaching package: ‘gridExtra’

The following object is masked from ‘package:dplyr’:

    combine
library(dplyr)
library(ggrepel)
library(plyr)
-----------------------------------------------------------------------------------
You have loaded plyr after dplyr - this is likely to cause problems.
If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
library(plyr); library(dplyr)
-----------------------------------------------------------------------------------

Attaching package: ‘plyr’

The following objects are masked from ‘package:dplyr’:

    arrange, count, desc, failwith, id, mutate, rename, summarise,
    summarize

The following object is masked from ‘package:purrr’:

    compact
## Finding the Arran coordinates
arrancoordinates <- read.csv("alldata/ukpostcodes.csv") %>%
filter(substr(postcode,1,4)=="KA27")
pcs <- read_sf("alldata/Scotland_pcs_2011")
arransubsect <- filter(pcs,substr(label,1,4)=="KA27")
#Import SIMD data from http://www.gov.scot/Topics/Statistics/SIMD
#https://data.gov.uk/dataset/scottish-index-of-multiple-deprivation-simd-2012
#https://data.gov.uk/dataset/scottish-index-of-multiple-deprivation-simd-2012/resource/d6fa8924-83da-4e80-a560-4ef0477f230b
DZBoundaries2016 <- read_sf("./alldata/SG_SIMD_2016")
DZBoundaries2012 <- read_sf("./alldata/SG_SIMD_2012")
DZBoundaries2009 <- read_sf("./alldata/SG_SIMD_2009")
DZBoundaries2006 <- read_sf("./alldata/SG_SIMD_2006")
DZBoundaries2004 <- read_sf("./alldata/SG_SIMD_2004")
#Selecting Arran data from Scotland (2016)
#Find postcode look-up from below file for KA27 postcodes. Find unique DZ. Find row positions.
#SIMD2016 <-read.csv("./alldata/00505244.csv")
#Selecting ArranDZ2016
Arrandz2016 <- c(4672,4666,4669,4671,4667,4668,4670)
arran2016 <- DZBoundaries2016[Arrandz2016,]
#Reorder arran 2016
reorderedvector<- c("S01011174", "S01011171", "S01011177", "S01011176", "S01011175", "S01011173", "S01011172" )
arran2016 <- arran2016 %>%
  slice(match(reorderedvector, DataZone))
#Find postcode look-up, KA27 postcodes. Find unique DZ. Find row positions.
#Selecting ArranDZ2012
Arrandz2012 <- c(4409,4372,4353,4352,4351,4350,4349)
#2012
arran2012 <- DZBoundaries2012[Arrandz2012,]
#2009
arran2009 <- DZBoundaries2009[Arrandz2012,]
#2006
arran2006 <- DZBoundaries2006[Arrandz2012,]
#2004
arran2004 <- DZBoundaries2004[Arrandz2012,]
arran20162 <- arran2016 %>%
  select(DataZone, geometry, Percentile)  %>%
  mutate(year="2016")
arran20122 <- arran2012 %>%
  select(DataZone, geometry, Percentile) %>%
  mutate(year="2012")
arran20092 <- arran2009 %>%
  select(DataZone, geometry, Percentile) %>%
  mutate(year="2009")
arran20062 <- arran2006 %>%
  select(DataZone, geometry, Percentile) %>%
  mutate(year="2006")
arran20042 <- arran2004 %>%
  select(DataZone, geometry, Percentile) %>%
  mutate(year="2004")
#Now I add it together
arransimd <- rbind(arran20162,arran20122,arran20092,arran20062,arran20042)
simple.sf <- st_as_sf(arrancoordinates, coords=c('longitude','latitude'))
st_crs(simple.sf) <- 4326
exampleshapes <- sf:::as_Spatial(arran2016$geometry)
examplepoints <- sf:::as_Spatial(simple.sf$geom)
examplepoints <- spTransform(examplepoints, CRS("+proj=longlat +datum=WGS84"))
exampleshapes <- spTransform(exampleshapes, CRS("+proj=longlat +datum=WGS84"))
namingdzpostcode <- over(exampleshapes, examplepoints, returnList = TRUE)

mutate arrancoordinates

function100 <- function(argument) 
{
  argument <- arrancoordinates[namingdzpostcode[[argument]],] %>% mutate(DataZone=argument)
}
function100(1)
newarrancoordinates <- lapply(1:7,function100)
newarrancoordinates <- rbind(newarrancoordinates[[1]], newarrancoordinates[[2]], newarrancoordinates[[3]], newarrancoordinates[[4]], newarrancoordinates[[5]], newarrancoordinates[[6]], newarrancoordinates[[7]])
newarrancoordinates$listID <- revalue(as.character(newarrancoordinates$DataZone),
               c('1'="S01004409/S01011174", '2'="S01004372/S01011171", '3'="S01004353/S01011177", '4'="S01004352/S01011176", '5'="S01004351/S01011175", '6'="S01004350/S01011173", '7'="S01004349/S01011172"))

///

arransimd$listID <- revalue(arransimd$DataZone,
               c("S01004409"="S01004409/S01011174", "S01004372"="S01004372/S01011171", "S01004353"="S01004353/S01011177", "S01004352"="S01004352/S01011176", "S01004351"="S01004351/S01011175", "S01004350"="S01004350/S01011173", "S01004349"="S01004349/S01011172", "S01011174"="S01004409/S01011174", "S01011171"="S01004372/S01011171", "S01011177"="S01004353/S01011177", "S01011176"="S01004352/S01011176", "S01011175"="S01004351/S01011175", "S01011173"="S01004350/S01011173", "S01011172"="S01004349/S01011172"))
arransimd %>%
mutate(
    lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
    lat = map_dbl(geometry, ~st_centroid(.x)[[2]])
    ) %>%
ggplot() +
  geom_sf(aes(fill = Percentile)) +
  facet_grid(listID ~ year) +
  theme_grey() +
  geom_text(aes(label = Percentile, x = lon, y = lat), size = 2, colour = "white") +
  theme(axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank()) +
  theme(legend.position="bottom")

arransimd %>%
mutate(
    lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
    lat = map_dbl(geometry, ~st_centroid(.x)[[2]])
    ) %>%
ggplot() +
  geom_sf(aes(fill = Percentile)) +
  facet_grid(year ~ listID) +
  theme_grey() +
  geom_text(aes(label = Percentile, x = lon, y = lat), size = 2, colour = "white") +
  theme(axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank()) +
  theme(legend.position="bottom")  

filter(arransimd, year == 2016) %>%
  ggplot() +
  theme_grey() +
  theme(axis.text.x=element_blank(),
        axis.ticks.x=element_blank()) +
  theme(legend.position="none") +
  facet_wrap('listID', nrow = 1) +
  geom_sf(aes(fill = DataZone))

function5 <- function(argument, argument2) 
{
  argument %>%
  ggplot() +
  geom_sf() +
  theme_grey() +
  geom_point(data=function6(argument2), mapping = aes(x = longitude, y = latitude), size=1) +
  theme(axis.title.x = element_blank(),
        axis.title.y = element_blank()) +
  coord_sf(crs= 4326, datum = sf::st_crs(4326))
}
filter(arransimd, year == 2016) %>%
  ggplot() +
  theme_grey() +
  theme(axis.text.x=element_blank(),
        axis.ticks.x=element_blank()) +
  theme(legend.position="none") +
  facet_wrap('listID', nrow = 1) +
  geom_sf() 

ggplot() +
  geom_point(data=newarrancoordinates, 
             mapping = aes(x = longitude, y = latitude), 
             size=1) +
  theme_grey() +
  theme(axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank()) +
  coord_sf(crs= 4326, datum = sf::st_crs(4326)) +
  facet_wrap('listID', nrow = 1)

ggplot() +
  geom_sf(data=arransimd) +
  geom_point(data=newarrancoordinates, 
             mapping = aes(x = longitude, y = latitude), 
             size=1) +
  theme_grey() +
  theme(axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank()) +
  coord_sf(crs= 4326, datum = sf::st_crs(4326)) +
  facet_wrap('listID', nrow = 1)

Function 8

simple.sf <- st_as_sf(arrancoordinates, coords=c('longitude','latitude'))
st_crs(simple.sf) <- 4326
exampleshapes <- sf:::as_Spatial(arran20162$geometry)
examplepoints <- sf:::as_Spatial(simple.sf$geom)
examplepoints <- spTransform(examplepoints, CRS("+proj=longlat +datum=WGS84"))
exampleshapes <- spTransform(exampleshapes, CRS("+proj=longlat +datum=WGS84"))
namingdzpostcode <- over(exampleshapes, examplepoints, returnList = TRUE)
function0.5 <- function(argument) 
{
  filter(arransimd, DataZone==argument)
}
#pre2016listID <- list(3,2,1,4,7,6,5)
#post2016listID <- list(1,2,3,4,5,6,7)
#pre2016listID2 <- list(1,2,3,4,5,6,7)
#post2016listID2 <- list(1,2,3,4,5,6,7)
listID <- list(1,2,3,4,5,6,7)
#all datazones
#datazonelist <- lapply(datazones, function0.5)
#Pre-2016 lists
pre2016list2 <- list("S01004409", "S01004372", "S01004353", "S01004352", "S01004351", "S01004350", "S01004349")
pre2016list <- lapply(pre2016list2, function0.5)
#post2016list2 <- list("S01011177", "S01011171", "S01011174", "S01011176", "S01011172", "S01011173", "S01011175")
#post2016list <- lapply(post2016list2, function0.5)
post2016list3 <- list("S01011174", "S01011171", "S01011177", "S01011176", "S01011175", "S01011173", "S01011172" )
post2016list2 <- lapply(post2016list3, function0.5)
#rearrange arrancoord
function6 <- function(argument) 
{
  arrancoordinates[namingdzpostcode[[argument]],]
}
function5 <- function(argument, argument2) 
{
  argument %>%
  ggplot() +
  geom_sf() +
  theme_grey() +
  geom_point(data=function6(argument2), mapping = aes(x = longitude, y = latitude), size=1) +
  theme(axis.title.x = element_blank(),
        axis.title.y = element_blank()) +
  coord_sf(crs= 4326, datum = sf::st_crs(4326))
}
function7.5.1 <- function(argument, argument2) 
{
  a <- function1.5.5(argument)
  b <- function2.5.1(argument) 
  c <- function5(argument, argument2)
  grid.arrange(a, b, c, nrow = 1)
}
function1.5.5 <- function(argument) 
{
  argument %>%
mutate(
    lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
    lat = map_dbl(geometry, ~st_centroid(.x)[[2]])
    ) %>%
  ggplot() +
  geom_sf(aes(fill = Percentile)) +
  facet_wrap('year') +
  theme_grey() +
  geom_text(aes(label = Percentile, x = lon, y = lat), size = 2, colour = "white") +
  theme(axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank()) +
  theme(legend.position="bottom")  
}
function2.5.1 <- function(argument) 
{
  arransubsect %>%
  ggplot() +
  geom_sf() +
  theme_grey() +
  theme(axis.text.x=element_text(angle=45, hjust = 1)) +
  theme(legend.position="bottom") +
  geom_sf(data= argument, aes(fill = DataZone))
}
function5 <- function(argument, argument2) 
{
  argument %>%
  ggplot() +
  geom_sf() +
  theme_grey() +
  geom_point(data=function6(argument2), mapping = aes(x = longitude, y = latitude), size=1) +
  theme(axis.title.x = element_blank(),
        axis.title.y = element_blank()) +
  coord_sf(crs= 4326, datum = sf::st_crs(4326))
}
function8.pre <- function(argument)
{
  function7.5.1(pre2016list[[argument]],listID[[argument]])
}
lapply(1:7, function8.pre)
[[1]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[2]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[3]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[4]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[5]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[6]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[7]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

function8.post <- function(argument)
{
  function7.5.1(post2016list2[[argument]],listID[[argument]])
}
lapply(1:7, function8.post)
[[1]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[2]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[3]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[4]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[5]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[6]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[7]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

function10 <- function(argument)
{
a <- arransimd %>%
mutate(
    lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
    lat = map_dbl(geometry, ~st_centroid(.x)[[2]])
    ) %>%
filter(listID == argument)  %>%
  ggplot() +
  geom_sf(aes(fill = Percentile)) +
  facet_wrap('year') +
  theme_grey() +
  geom_text(aes(label = Percentile, x = lon, y = lat), size = 2, colour = "white") +
  theme(axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank()) +
  theme(legend.position="bottom")  
b <- arransimd %>%
  filter(listID == argument)  %>%
  ggplot() +
  geom_sf(data = arransubsect) +
  theme_grey() +
  theme(axis.text.x=element_text(angle=45, hjust = 1)) +
  theme(legend.position="bottom") +
  geom_sf(aes(fill = DataZone))
c <- arransimd %>%
  filter(listID == argument)  %>%
  ggplot() +
  geom_sf() +
  theme_grey() +
  geom_point(data = filter(newarrancoordinates, listID == argument), 
             mapping = aes(x = longitude, y = latitude), size=1) +
  geom_text_repel(data = filter(newarrancoordinates, listID == argument), 
            aes(label = filter(newarrancoordinates, 
                               listID == argument)$postcode, 
                x = longitude, y = latitude), size=2) +
  theme(axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank()) +
  coord_sf(crs= 4326, datum = sf::st_crs(4326))
grid.arrange(a, b, c, nrow = 1)
}

create as list down side instead?

create template to selectively display postcodes

lapply(unique(arransimd$listID), function10)
[[1]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[2]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[3]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[4]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[5]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[6]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[7]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

function10.5 <- function(argument)
{
a <- arransimd %>%
mutate(
    lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
    lat = map_dbl(geometry, ~st_centroid(.x)[[2]])
    ) %>%
filter(listID == argument)  %>%
  ggplot() +
  geom_sf(aes(fill = Percentile)) +
  facet_wrap('year') +
  theme_grey() +
  geom_text(aes(label = Percentile, x = lon, y = lat), size = 2, colour = "white") +
  theme(axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank()) +
  theme(legend.position="none") +
  ggtitle(argument)  
b <- arransimd %>%
  filter(listID == argument)  %>%
  ggplot() +
  geom_sf(data = arransubsect) +
  theme_grey() +
  theme(axis.text.x=element_text(angle=45, hjust = 1)) +
  theme(legend.position="none") +
  geom_sf(aes(fill = DataZone))
c <- arransimd %>%
  filter(listID == argument)  %>%
  ggplot() +
  geom_sf() +
  theme_grey() +
  geom_point(data = filter(newarrancoordinates, listID == argument), 
             mapping = aes(x = longitude, y = latitude), size=1) +
  geom_text_repel(data = filter(newarrancoordinates, listID == argument), 
            aes(label = filter(newarrancoordinates, 
                               listID == argument)$postcode, 
                x = longitude, y = latitude), size=2) +
  theme(axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank()) +
  coord_sf(crs= 4326, datum = sf::st_crs(4326))
grid.arrange(a, b, c, nrow = 1)
}
lapply(unique(arransimd$listID), function10.5)
[[1]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[2]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[3]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[4]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[5]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[6]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

[[7]]
TableGrob (1 x 3) "arrange": 3 grobs
  z     cells    name           grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (1-1,2-2) arrange gtable[layout]
3 3 (1-1,3-3) arrange gtable[layout]

a <- arransimd %>% mutate( lon = map_dbl(geometry, ~st_centroid(.x)[[1]]), lat = map_dbl(geometry, ~st_centroid(.x)[[2]]) ) %>% ggplot() + geom_sf(aes(fill = Percentile)) + facet_wrap(listID ~ year) + theme_grey() + geom_text(aes(label = Percentile, x = lon, y = lat), size = 2, colour = “white”) + theme(axis.text.x=element_blank(), axis.ticks.x=element_blank(), axis.text.y=element_blank(), axis.ticks.y=element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank()) + theme(legend.position=“bottom”)

b <- arransimd %>% ggplot() + geom_sf(data = arransubsect) + theme_grey() + theme(axis.text.x=element_text(angle=45, hjust = 1)) + theme(legend.position=“bottom”) + geom_sf(aes(fill = DataZone))

c <- arransimd %>% ggplot() + geom_sf() + theme_grey() + geom_point(data = filter(newarrancoordinates, listID == argument), mapping = aes(x = longitude, y = latitude), size=1) + geom_text_repel(data = filter(newarrancoordinates, listID == argument), aes(label = filter(newarrancoordinates, listID == argument)$postcode, x = longitude, y = latitude), size=2) + theme(axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank(), axis.text.y=element_blank(), axis.ticks.y=element_blank()) + coord_sf(crs= 4326, datum = sf::st_crs(4326))

grid.arrange(a, b, c, nrow = 1)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgZ2l0aHViX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKYGBge3J9CmxpYnJhcnkoc2YpCmxpYnJhcnkoZ2dwbG90MikgI2RldmVsb3BtZW50IHZlcnNpb24hCiMjIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigidGlkeXZlcnNlL2dncGxvdDIiKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkcikKIyMgTm90IHN1cmUgYWJvdXQgdGhpcyBiaXQKI2xpYnJhcnkoInRpZHl2ZXJzZSIsbGliLmxvYz0iL0xpYnJhcnkvRnJhbWV3b3Jrcy9SLmZyYW1ld29yay9WZXJzaW9ucy8zLjQvUmVzb3VyY2VzL2xpYnJhcnkiKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoc3ApCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkocGx5cikKYGBgCgpgYGB7cn0KIyMgRmluZGluZyB0aGUgQXJyYW4gY29vcmRpbmF0ZXMKYXJyYW5jb29yZGluYXRlcyA8LSByZWFkLmNzdigiYWxsZGF0YS91a3Bvc3Rjb2Rlcy5jc3YiKSAlPiUKZmlsdGVyKHN1YnN0cihwb3N0Y29kZSwxLDQpPT0iS0EyNyIpCgpwY3MgPC0gcmVhZF9zZigiYWxsZGF0YS9TY290bGFuZF9wY3NfMjAxMSIpCmFycmFuc3Vic2VjdCA8LSBmaWx0ZXIocGNzLHN1YnN0cihsYWJlbCwxLDQpPT0iS0EyNyIpCmBgYAoKYGBge3J9CiNJbXBvcnQgU0lNRCBkYXRhIGZyb20gaHR0cDovL3d3dy5nb3Yuc2NvdC9Ub3BpY3MvU3RhdGlzdGljcy9TSU1ECiNodHRwczovL2RhdGEuZ292LnVrL2RhdGFzZXQvc2NvdHRpc2gtaW5kZXgtb2YtbXVsdGlwbGUtZGVwcml2YXRpb24tc2ltZC0yMDEyCiNodHRwczovL2RhdGEuZ292LnVrL2RhdGFzZXQvc2NvdHRpc2gtaW5kZXgtb2YtbXVsdGlwbGUtZGVwcml2YXRpb24tc2ltZC0yMDEyL3Jlc291cmNlL2Q2ZmE4OTI0LTgzZGEtNGU4MC1hNTYwLTRlZjA0NzdmMjMwYgpEWkJvdW5kYXJpZXMyMDE2IDwtIHJlYWRfc2YoIi4vYWxsZGF0YS9TR19TSU1EXzIwMTYiKQpEWkJvdW5kYXJpZXMyMDEyIDwtIHJlYWRfc2YoIi4vYWxsZGF0YS9TR19TSU1EXzIwMTIiKQpEWkJvdW5kYXJpZXMyMDA5IDwtIHJlYWRfc2YoIi4vYWxsZGF0YS9TR19TSU1EXzIwMDkiKQpEWkJvdW5kYXJpZXMyMDA2IDwtIHJlYWRfc2YoIi4vYWxsZGF0YS9TR19TSU1EXzIwMDYiKQpEWkJvdW5kYXJpZXMyMDA0IDwtIHJlYWRfc2YoIi4vYWxsZGF0YS9TR19TSU1EXzIwMDQiKQpgYGAKCmBgYHtyfQojU2VsZWN0aW5nIEFycmFuIGRhdGEgZnJvbSBTY290bGFuZCAoMjAxNikKI0ZpbmQgcG9zdGNvZGUgbG9vay11cCBmcm9tIGJlbG93IGZpbGUgZm9yIEtBMjcgcG9zdGNvZGVzLiBGaW5kIHVuaXF1ZSBEWi4gRmluZCByb3cgcG9zaXRpb25zLgojU0lNRDIwMTYgPC1yZWFkLmNzdigiLi9hbGxkYXRhLzAwNTA1MjQ0LmNzdiIpCiNTZWxlY3RpbmcgQXJyYW5EWjIwMTYKQXJyYW5kejIwMTYgPC0gYyg0NjcyLDQ2NjYsNDY2OSw0NjcxLDQ2NjcsNDY2OCw0NjcwKQphcnJhbjIwMTYgPC0gRFpCb3VuZGFyaWVzMjAxNltBcnJhbmR6MjAxNixdCiNSZW9yZGVyIGFycmFuIDIwMTYKcmVvcmRlcmVkdmVjdG9yPC0gYygiUzAxMDExMTc0IiwgIlMwMTAxMTE3MSIsICJTMDEwMTExNzciLCAiUzAxMDExMTc2IiwgIlMwMTAxMTE3NSIsICJTMDEwMTExNzMiLCAiUzAxMDExMTcyIiApCmFycmFuMjAxNiA8LSBhcnJhbjIwMTYgJT4lCiAgc2xpY2UobWF0Y2gocmVvcmRlcmVkdmVjdG9yLCBEYXRhWm9uZSkpCgojRmluZCBwb3N0Y29kZSBsb29rLXVwLCBLQTI3IHBvc3Rjb2Rlcy4gRmluZCB1bmlxdWUgRFouIEZpbmQgcm93IHBvc2l0aW9ucy4KI1NlbGVjdGluZyBBcnJhbkRaMjAxMgpBcnJhbmR6MjAxMiA8LSBjKDQ0MDksNDM3Miw0MzUzLDQzNTIsNDM1MSw0MzUwLDQzNDkpCgojMjAxMgphcnJhbjIwMTIgPC0gRFpCb3VuZGFyaWVzMjAxMltBcnJhbmR6MjAxMixdCiMyMDA5CmFycmFuMjAwOSA8LSBEWkJvdW5kYXJpZXMyMDA5W0FycmFuZHoyMDEyLF0KIzIwMDYKYXJyYW4yMDA2IDwtIERaQm91bmRhcmllczIwMDZbQXJyYW5kejIwMTIsXQojMjAwNAphcnJhbjIwMDQgPC0gRFpCb3VuZGFyaWVzMjAwNFtBcnJhbmR6MjAxMixdCmBgYAoKYGBge3J9CmFycmFuMjAxNjIgPC0gYXJyYW4yMDE2ICU+JQogIHNlbGVjdChEYXRhWm9uZSwgZ2VvbWV0cnksIFBlcmNlbnRpbGUpICAlPiUKICBtdXRhdGUoeWVhcj0iMjAxNiIpCgphcnJhbjIwMTIyIDwtIGFycmFuMjAxMiAlPiUKICBzZWxlY3QoRGF0YVpvbmUsIGdlb21ldHJ5LCBQZXJjZW50aWxlKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAxMiIpCgphcnJhbjIwMDkyIDwtIGFycmFuMjAwOSAlPiUKICBzZWxlY3QoRGF0YVpvbmUsIGdlb21ldHJ5LCBQZXJjZW50aWxlKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAwOSIpCgphcnJhbjIwMDYyIDwtIGFycmFuMjAwNiAlPiUKICBzZWxlY3QoRGF0YVpvbmUsIGdlb21ldHJ5LCBQZXJjZW50aWxlKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAwNiIpCgphcnJhbjIwMDQyIDwtIGFycmFuMjAwNCAlPiUKICBzZWxlY3QoRGF0YVpvbmUsIGdlb21ldHJ5LCBQZXJjZW50aWxlKSAlPiUKICBtdXRhdGUoeWVhcj0iMjAwNCIpCgojTm93IEkgYWRkIGl0IHRvZ2V0aGVyCmFycmFuc2ltZCA8LSByYmluZChhcnJhbjIwMTYyLGFycmFuMjAxMjIsYXJyYW4yMDA5MixhcnJhbjIwMDYyLGFycmFuMjAwNDIpCmBgYAoKYGBge3J9CnNpbXBsZS5zZiA8LSBzdF9hc19zZihhcnJhbmNvb3JkaW5hdGVzLCBjb29yZHM9YygnbG9uZ2l0dWRlJywnbGF0aXR1ZGUnKSkKc3RfY3JzKHNpbXBsZS5zZikgPC0gNDMyNgoKZXhhbXBsZXNoYXBlcyA8LSBzZjo6OmFzX1NwYXRpYWwoYXJyYW4yMDE2JGdlb21ldHJ5KQpleGFtcGxlcG9pbnRzIDwtIHNmOjo6YXNfU3BhdGlhbChzaW1wbGUuc2YkZ2VvbSkKCmV4YW1wbGVwb2ludHMgPC0gc3BUcmFuc2Zvcm0oZXhhbXBsZXBvaW50cywgQ1JTKCIrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCIpKQpleGFtcGxlc2hhcGVzIDwtIHNwVHJhbnNmb3JtKGV4YW1wbGVzaGFwZXMsIENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKCm5hbWluZ2R6cG9zdGNvZGUgPC0gb3ZlcihleGFtcGxlc2hhcGVzLCBleGFtcGxlcG9pbnRzLCByZXR1cm5MaXN0ID0gVFJVRSkKYGBgCgojbXV0YXRlIGFycmFuY29vcmRpbmF0ZXMKYGBge3J9CmZ1bmN0aW9uMTAwIDwtIGZ1bmN0aW9uKGFyZ3VtZW50KSAKewogIGFyZ3VtZW50IDwtIGFycmFuY29vcmRpbmF0ZXNbbmFtaW5nZHpwb3N0Y29kZVtbYXJndW1lbnRdXSxdICU+JSBtdXRhdGUoRGF0YVpvbmU9YXJndW1lbnQpCn0KCmZ1bmN0aW9uMTAwKDEpCgpuZXdhcnJhbmNvb3JkaW5hdGVzIDwtIGxhcHBseSgxOjcsZnVuY3Rpb24xMDApCm5ld2FycmFuY29vcmRpbmF0ZXMgPC0gcmJpbmQobmV3YXJyYW5jb29yZGluYXRlc1tbMV1dLCBuZXdhcnJhbmNvb3JkaW5hdGVzW1syXV0sIG5ld2FycmFuY29vcmRpbmF0ZXNbWzNdXSwgbmV3YXJyYW5jb29yZGluYXRlc1tbNF1dLCBuZXdhcnJhbmNvb3JkaW5hdGVzW1s1XV0sIG5ld2FycmFuY29vcmRpbmF0ZXNbWzZdXSwgbmV3YXJyYW5jb29yZGluYXRlc1tbN11dKQoKbmV3YXJyYW5jb29yZGluYXRlcyRsaXN0SUQgPC0gcmV2YWx1ZShhcy5jaGFyYWN0ZXIobmV3YXJyYW5jb29yZGluYXRlcyREYXRhWm9uZSksCiAgICAgICAgICAgICAgIGMoJzEnPSJTMDEwMDQ0MDkvUzAxMDExMTc0IiwgJzInPSJTMDEwMDQzNzIvUzAxMDExMTcxIiwgJzMnPSJTMDEwMDQzNTMvUzAxMDExMTc3IiwgJzQnPSJTMDEwMDQzNTIvUzAxMDExMTc2IiwgJzUnPSJTMDEwMDQzNTEvUzAxMDExMTc1IiwgJzYnPSJTMDEwMDQzNTAvUzAxMDExMTczIiwgJzcnPSJTMDEwMDQzNDkvUzAxMDExMTcyIikpCmBgYAoKLy8vCgpgYGB7cn0KYXJyYW5zaW1kJGxpc3RJRCA8LSByZXZhbHVlKGFycmFuc2ltZCREYXRhWm9uZSwKICAgICAgICAgICAgICAgYygiUzAxMDA0NDA5Ij0iUzAxMDA0NDA5L1MwMTAxMTE3NCIsICJTMDEwMDQzNzIiPSJTMDEwMDQzNzIvUzAxMDExMTcxIiwgIlMwMTAwNDM1MyI9IlMwMTAwNDM1My9TMDEwMTExNzciLCAiUzAxMDA0MzUyIj0iUzAxMDA0MzUyL1MwMTAxMTE3NiIsICJTMDEwMDQzNTEiPSJTMDEwMDQzNTEvUzAxMDExMTc1IiwgIlMwMTAwNDM1MCI9IlMwMTAwNDM1MC9TMDEwMTExNzMiLCAiUzAxMDA0MzQ5Ij0iUzAxMDA0MzQ5L1MwMTAxMTE3MiIsICJTMDEwMTExNzQiPSJTMDEwMDQ0MDkvUzAxMDExMTc0IiwgIlMwMTAxMTE3MSI9IlMwMTAwNDM3Mi9TMDEwMTExNzEiLCAiUzAxMDExMTc3Ij0iUzAxMDA0MzUzL1MwMTAxMTE3NyIsICJTMDEwMTExNzYiPSJTMDEwMDQzNTIvUzAxMDExMTc2IiwgIlMwMTAxMTE3NSI9IlMwMTAwNDM1MS9TMDEwMTExNzUiLCAiUzAxMDExMTczIj0iUzAxMDA0MzUwL1MwMTAxMTE3MyIsICJTMDEwMTExNzIiPSJTMDEwMDQzNDkvUzAxMDExMTcyIikpCgphcnJhbnNpbWQgJT4lCm11dGF0ZSgKICAgIGxvbiA9IG1hcF9kYmwoZ2VvbWV0cnksIH5zdF9jZW50cm9pZCgueClbWzFdXSksCiAgICBsYXQgPSBtYXBfZGJsKGdlb21ldHJ5LCB+c3RfY2VudHJvaWQoLngpW1syXV0pCiAgICApICU+JQpnZ3Bsb3QoKSArCiAgZ2VvbV9zZihhZXMoZmlsbCA9IFBlcmNlbnRpbGUpKSArCiAgZmFjZXRfZ3JpZChsaXN0SUQgfiB5ZWFyKSArCiAgdGhlbWVfZ3JleSgpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gUGVyY2VudGlsZSwgeCA9IGxvbiwgeSA9IGxhdCksIHNpemUgPSAyLCBjb2xvdXIgPSAid2hpdGUiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikKYGBgCgpgYGB7cn0KYXJyYW5zaW1kICU+JQptdXRhdGUoCiAgICBsb24gPSBtYXBfZGJsKGdlb21ldHJ5LCB+c3RfY2VudHJvaWQoLngpW1sxXV0pLAogICAgbGF0ID0gbWFwX2RibChnZW9tZXRyeSwgfnN0X2NlbnRyb2lkKC54KVtbMl1dKQogICAgKSAlPiUKZ2dwbG90KCkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBQZXJjZW50aWxlKSkgKwogIGZhY2V0X2dyaWQoeWVhciB+IGxpc3RJRCkgKwogIHRoZW1lX2dyZXkoKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBlcmNlbnRpbGUsIHggPSBsb24sIHkgPSBsYXQpLCBzaXplID0gMiwgY29sb3VyID0gIndoaXRlIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICAKYGBgCgoKYGBge3J9CmZpbHRlcihhcnJhbnNpbWQsIHllYXIgPT0gMjAxNikgJT4lCiAgZ2dwbG90KCkgKwogIHRoZW1lX2dyZXkoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZmFjZXRfd3JhcCgnbGlzdElEJywgbnJvdyA9IDEpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gRGF0YVpvbmUpKQpgYGAKCmBgYHtyfQpmdW5jdGlvbjUgPC0gZnVuY3Rpb24oYXJndW1lbnQsIGFyZ3VtZW50MikgCnsKICBhcmd1bWVudCAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZigpICsKICB0aGVtZV9ncmV5KCkgKwogIGdlb21fcG9pbnQoZGF0YT1mdW5jdGlvbjYoYXJndW1lbnQyKSwgbWFwcGluZyA9IGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUpLCBzaXplPTEpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgY29vcmRfc2YoY3JzPSA0MzI2LCBkYXR1bSA9IHNmOjpzdF9jcnMoNDMyNikpCn0KCmZpbHRlcihhcnJhbnNpbWQsIHllYXIgPT0gMjAxNikgJT4lCiAgZ2dwbG90KCkgKwogIHRoZW1lX2dyZXkoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZmFjZXRfd3JhcCgnbGlzdElEJywgbnJvdyA9IDEpICsKICBnZW9tX3NmKCkgCmBgYAoKYGBge3J9CmdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGE9bmV3YXJyYW5jb29yZGluYXRlcywgCiAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIAogICAgICAgICAgICAgc2l6ZT0xKSArCiAgdGhlbWVfZ3JleSgpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpKSArCiAgY29vcmRfc2YoY3JzPSA0MzI2LCBkYXR1bSA9IHNmOjpzdF9jcnMoNDMyNikpICsKICBmYWNldF93cmFwKCdsaXN0SUQnLCBucm93ID0gMSkKCmBgYAoKYGBge3J9CmdncGxvdCgpICsKICBnZW9tX3NmKGRhdGE9YXJyYW5zaW1kKSArCiAgZ2VvbV9wb2ludChkYXRhPW5ld2FycmFuY29vcmRpbmF0ZXMsIAogICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUpLCAKICAgICAgICAgICAgIHNpemU9MSkgKwogIHRoZW1lX2dyZXkoKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSkgKwogIGNvb3JkX3NmKGNycz0gNDMyNiwgZGF0dW0gPSBzZjo6c3RfY3JzKDQzMjYpKSArCiAgZmFjZXRfd3JhcCgnbGlzdElEJywgbnJvdyA9IDEpCmBgYAoKI0Z1bmN0aW9uIDgKYGBge3J9CnNpbXBsZS5zZiA8LSBzdF9hc19zZihhcnJhbmNvb3JkaW5hdGVzLCBjb29yZHM9YygnbG9uZ2l0dWRlJywnbGF0aXR1ZGUnKSkKc3RfY3JzKHNpbXBsZS5zZikgPC0gNDMyNgoKZXhhbXBsZXNoYXBlcyA8LSBzZjo6OmFzX1NwYXRpYWwoYXJyYW4yMDE2MiRnZW9tZXRyeSkKZXhhbXBsZXBvaW50cyA8LSBzZjo6OmFzX1NwYXRpYWwoc2ltcGxlLnNmJGdlb20pCgpleGFtcGxlcG9pbnRzIDwtIHNwVHJhbnNmb3JtKGV4YW1wbGVwb2ludHMsIENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKZXhhbXBsZXNoYXBlcyA8LSBzcFRyYW5zZm9ybShleGFtcGxlc2hhcGVzLCBDUlMoIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0IikpCgpuYW1pbmdkenBvc3Rjb2RlIDwtIG92ZXIoZXhhbXBsZXNoYXBlcywgZXhhbXBsZXBvaW50cywgcmV0dXJuTGlzdCA9IFRSVUUpCmBgYAoKYGBge3J9CmZ1bmN0aW9uMC41IDwtIGZ1bmN0aW9uKGFyZ3VtZW50KSAKewogIGZpbHRlcihhcnJhbnNpbWQsIERhdGFab25lPT1hcmd1bWVudCkKfQpgYGAKCmBgYHtyfQojcHJlMjAxNmxpc3RJRCA8LSBsaXN0KDMsMiwxLDQsNyw2LDUpCiNwb3N0MjAxNmxpc3RJRCA8LSBsaXN0KDEsMiwzLDQsNSw2LDcpCgojcHJlMjAxNmxpc3RJRDIgPC0gbGlzdCgxLDIsMyw0LDUsNiw3KQojcG9zdDIwMTZsaXN0SUQyIDwtIGxpc3QoMSwyLDMsNCw1LDYsNykKCmxpc3RJRCA8LSBsaXN0KDEsMiwzLDQsNSw2LDcpCgojYWxsIGRhdGF6b25lcwojZGF0YXpvbmVsaXN0IDwtIGxhcHBseShkYXRhem9uZXMsIGZ1bmN0aW9uMC41KQoKI1ByZS0yMDE2IGxpc3RzCnByZTIwMTZsaXN0MiA8LSBsaXN0KCJTMDEwMDQ0MDkiLCAiUzAxMDA0MzcyIiwgIlMwMTAwNDM1MyIsICJTMDEwMDQzNTIiLCAiUzAxMDA0MzUxIiwgIlMwMTAwNDM1MCIsICJTMDEwMDQzNDkiKQpwcmUyMDE2bGlzdCA8LSBsYXBwbHkocHJlMjAxNmxpc3QyLCBmdW5jdGlvbjAuNSkKCiNwb3N0MjAxNmxpc3QyIDwtIGxpc3QoIlMwMTAxMTE3NyIsICJTMDEwMTExNzEiLCAiUzAxMDExMTc0IiwgIlMwMTAxMTE3NiIsICJTMDEwMTExNzIiLCAiUzAxMDExMTczIiwgIlMwMTAxMTE3NSIpCiNwb3N0MjAxNmxpc3QgPC0gbGFwcGx5KHBvc3QyMDE2bGlzdDIsIGZ1bmN0aW9uMC41KQoKcG9zdDIwMTZsaXN0MyA8LSBsaXN0KCJTMDEwMTExNzQiLCAiUzAxMDExMTcxIiwgIlMwMTAxMTE3NyIsICJTMDEwMTExNzYiLCAiUzAxMDExMTc1IiwgIlMwMTAxMTE3MyIsICJTMDEwMTExNzIiICkKcG9zdDIwMTZsaXN0MiA8LSBsYXBwbHkocG9zdDIwMTZsaXN0MywgZnVuY3Rpb24wLjUpCmBgYAoKYGBge3J9CiNyZWFycmFuZ2UgYXJyYW5jb29yZApmdW5jdGlvbjYgPC0gZnVuY3Rpb24oYXJndW1lbnQpIAp7CiAgYXJyYW5jb29yZGluYXRlc1tuYW1pbmdkenBvc3Rjb2RlW1thcmd1bWVudF1dLF0KfQpgYGAKCmBgYHtyfQpmdW5jdGlvbjUgPC0gZnVuY3Rpb24oYXJndW1lbnQsIGFyZ3VtZW50MikgCnsKICBhcmd1bWVudCAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZigpICsKICB0aGVtZV9ncmV5KCkgKwogIGdlb21fcG9pbnQoZGF0YT1mdW5jdGlvbjYoYXJndW1lbnQyKSwgbWFwcGluZyA9IGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUpLCBzaXplPTEpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgY29vcmRfc2YoY3JzPSA0MzI2LCBkYXR1bSA9IHNmOjpzdF9jcnMoNDMyNikpCn0KYGBgCgpgYGB7cn0KZnVuY3Rpb243LjUuMSA8LSBmdW5jdGlvbihhcmd1bWVudCwgYXJndW1lbnQyKSAKewogIGEgPC0gZnVuY3Rpb24xLjUuNShhcmd1bWVudCkKICBiIDwtIGZ1bmN0aW9uMi41LjEoYXJndW1lbnQpIAogIGMgPC0gZnVuY3Rpb241KGFyZ3VtZW50LCBhcmd1bWVudDIpCiAgZ3JpZC5hcnJhbmdlKGEsIGIsIGMsIG5yb3cgPSAxKQp9CmBgYAoKYGBge3J9CmZ1bmN0aW9uMS41LjUgPC0gZnVuY3Rpb24oYXJndW1lbnQpIAp7CiAgYXJndW1lbnQgJT4lCm11dGF0ZSgKICAgIGxvbiA9IG1hcF9kYmwoZ2VvbWV0cnksIH5zdF9jZW50cm9pZCgueClbWzFdXSksCiAgICBsYXQgPSBtYXBfZGJsKGdlb21ldHJ5LCB+c3RfY2VudHJvaWQoLngpW1syXV0pCiAgICApICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gUGVyY2VudGlsZSkpICsKICBmYWNldF93cmFwKCd5ZWFyJykgKwogIHRoZW1lX2dyZXkoKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBlcmNlbnRpbGUsIHggPSBsb24sIHkgPSBsYXQpLCBzaXplID0gMiwgY29sb3VyID0gIndoaXRlIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICAKfQpgYGAKCmBgYHtyfQpmdW5jdGlvbjIuNS4xIDwtIGZ1bmN0aW9uKGFyZ3VtZW50KSAKewogIGFycmFuc3Vic2VjdCAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZigpICsKICB0aGVtZV9ncmV5KCkgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKwogIGdlb21fc2YoZGF0YT0gYXJndW1lbnQsIGFlcyhmaWxsID0gRGF0YVpvbmUpKQp9CmBgYAoKYGBge3J9CmZ1bmN0aW9uNSA8LSBmdW5jdGlvbihhcmd1bWVudCwgYXJndW1lbnQyKSAKewogIGFyZ3VtZW50ICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKCkgKwogIHRoZW1lX2dyZXkoKSArCiAgZ2VvbV9wb2ludChkYXRhPWZ1bmN0aW9uNihhcmd1bWVudDIpLCBtYXBwaW5nID0gYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIHNpemU9MSkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBjb29yZF9zZihjcnM9IDQzMjYsIGRhdHVtID0gc2Y6OnN0X2Nycyg0MzI2KSkKfQpgYGAKCmBgYHtyfQpmdW5jdGlvbjgucHJlIDwtIGZ1bmN0aW9uKGFyZ3VtZW50KQp7CiAgZnVuY3Rpb243LjUuMShwcmUyMDE2bGlzdFtbYXJndW1lbnRdXSxsaXN0SURbW2FyZ3VtZW50XV0pCn0KbGFwcGx5KDE6NywgZnVuY3Rpb244LnByZSkKCmZ1bmN0aW9uOC5wb3N0IDwtIGZ1bmN0aW9uKGFyZ3VtZW50KQp7CiAgZnVuY3Rpb243LjUuMShwb3N0MjAxNmxpc3QyW1thcmd1bWVudF1dLGxpc3RJRFtbYXJndW1lbnRdXSkKfQpsYXBwbHkoMTo3LCBmdW5jdGlvbjgucG9zdCkKYGBgCgpgYGB7cn0KZnVuY3Rpb24xMCA8LSBmdW5jdGlvbihhcmd1bWVudCkKewphIDwtIGFycmFuc2ltZCAlPiUKbXV0YXRlKAogICAgbG9uID0gbWFwX2RibChnZW9tZXRyeSwgfnN0X2NlbnRyb2lkKC54KVtbMV1dKSwKICAgIGxhdCA9IG1hcF9kYmwoZ2VvbWV0cnksIH5zdF9jZW50cm9pZCgueClbWzJdXSkKICAgICkgJT4lCmZpbHRlcihsaXN0SUQgPT0gYXJndW1lbnQpICAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihhZXMoZmlsbCA9IFBlcmNlbnRpbGUpKSArCiAgZmFjZXRfd3JhcCgneWVhcicpICsKICB0aGVtZV9ncmV5KCkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBQZXJjZW50aWxlLCB4ID0gbG9uLCB5ID0gbGF0KSwgc2l6ZSA9IDIsIGNvbG91ciA9ICJ3aGl0ZSIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSAgCgpiIDwtIGFycmFuc2ltZCAlPiUKICBmaWx0ZXIobGlzdElEID09IGFyZ3VtZW50KSAgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IGFycmFuc3Vic2VjdCkgKwogIHRoZW1lX2dyZXkoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdCA9IDEpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgZ2VvbV9zZihhZXMoZmlsbCA9IERhdGFab25lKSkKCmMgPC0gYXJyYW5zaW1kICU+JQogIGZpbHRlcihsaXN0SUQgPT0gYXJndW1lbnQpICAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZigpICsKICB0aGVtZV9ncmV5KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpbHRlcihuZXdhcnJhbmNvb3JkaW5hdGVzLCBsaXN0SUQgPT0gYXJndW1lbnQpLCAKICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlKSwgc2l6ZT0xKSArCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSBmaWx0ZXIobmV3YXJyYW5jb29yZGluYXRlcywgbGlzdElEID09IGFyZ3VtZW50KSwgCiAgICAgICAgICAgIGFlcyhsYWJlbCA9IGZpbHRlcihuZXdhcnJhbmNvb3JkaW5hdGVzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RJRCA9PSBhcmd1bWVudCkkcG9zdGNvZGUsIAogICAgICAgICAgICAgICAgeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlKSwgc2l6ZT0yKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkgKwogIGNvb3JkX3NmKGNycz0gNDMyNiwgZGF0dW0gPSBzZjo6c3RfY3JzKDQzMjYpKQoKZ3JpZC5hcnJhbmdlKGEsIGIsIGMsIG5yb3cgPSAxKQp9CmBgYAoKI2NyZWF0ZSBhcyBsaXN0IGRvd24gc2lkZSBpbnN0ZWFkPwojY3JlYXRlIHRlbXBsYXRlIHRvIHNlbGVjdGl2ZWx5IGRpc3BsYXkgcG9zdGNvZGVzCgpgYGB7cn0KbGFwcGx5KHVuaXF1ZShhcnJhbnNpbWQkbGlzdElEKSwgZnVuY3Rpb24xMCkKYGBgCgpgYGB7cn0KZnVuY3Rpb24xMC41IDwtIGZ1bmN0aW9uKGFyZ3VtZW50KQp7CmEgPC0gYXJyYW5zaW1kICU+JQptdXRhdGUoCiAgICBsb24gPSBtYXBfZGJsKGdlb21ldHJ5LCB+c3RfY2VudHJvaWQoLngpW1sxXV0pLAogICAgbGF0ID0gbWFwX2RibChnZW9tZXRyeSwgfnN0X2NlbnRyb2lkKC54KVtbMl1dKQogICAgKSAlPiUKZmlsdGVyKGxpc3RJRCA9PSBhcmd1bWVudCkgICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gUGVyY2VudGlsZSkpICsKICBmYWNldF93cmFwKCd5ZWFyJykgKwogIHRoZW1lX2dyZXkoKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBlcmNlbnRpbGUsIHggPSBsb24sIHkgPSBsYXQpLCBzaXplID0gMiwgY29sb3VyID0gIndoaXRlIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZ2d0aXRsZShhcmd1bWVudCkgIAoKYiA8LSBhcnJhbnNpbWQgJT4lCiAgZmlsdGVyKGxpc3RJRCA9PSBhcmd1bWVudCkgICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGRhdGEgPSBhcnJhbnN1YnNlY3QpICsKICB0aGVtZV9ncmV5KCkgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gRGF0YVpvbmUpKQoKYyA8LSBhcnJhbnNpbWQgJT4lCiAgZmlsdGVyKGxpc3RJRCA9PSBhcmd1bWVudCkgICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKCkgKwogIHRoZW1lX2dyZXkoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKG5ld2FycmFuY29vcmRpbmF0ZXMsIGxpc3RJRCA9PSBhcmd1bWVudCksIAogICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUpLCBzaXplPTEpICsKICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGZpbHRlcihuZXdhcnJhbmNvb3JkaW5hdGVzLCBsaXN0SUQgPT0gYXJndW1lbnQpLCAKICAgICAgICAgICAgYWVzKGxhYmVsID0gZmlsdGVyKG5ld2FycmFuY29vcmRpbmF0ZXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdElEID09IGFyZ3VtZW50KSRwb3N0Y29kZSwgCiAgICAgICAgICAgICAgICB4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUpLCBzaXplPTIpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArCiAgY29vcmRfc2YoY3JzPSA0MzI2LCBkYXR1bSA9IHNmOjpzdF9jcnMoNDMyNikpCgpncmlkLmFycmFuZ2UoYSwgYiwgYywgbnJvdyA9IDEpCn0KbGFwcGx5KHVuaXF1ZShhcnJhbnNpbWQkbGlzdElEKSwgZnVuY3Rpb24xMC41KQpgYGAKCmBgYHtyfQpmdW5jdGlvbjExIDwtIGZ1bmN0aW9uKGFyZ3VtZW50KQp7CmFycmFuc2ltZCAlPiUKICBmaWx0ZXIobGlzdElEID09IGFyZ3VtZW50KSAgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoKSArCiAgdGhlbWVfZ3JleSgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIobmV3YXJyYW5jb29yZGluYXRlcywgbGlzdElEID09IGFyZ3VtZW50KSwgCiAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIHNpemU9MSkgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gZmlsdGVyKG5ld2FycmFuY29vcmRpbmF0ZXMsIGxpc3RJRCA9PSBhcmd1bWVudCksIAogICAgICAgICAgICBhZXMobGFiZWwgPSBmaWx0ZXIobmV3YXJyYW5jb29yZGluYXRlcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0SUQgPT0gYXJndW1lbnQpJHBvc3Rjb2RlLCAKICAgICAgICAgICAgICAgIHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIHNpemU9MikgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpICsKICBjb29yZF9zZihjcnM9IDQzMjYsIGRhdHVtID0gc2Y6OnN0X2Nycyg0MzI2KSkKfQoKZnVuY3Rpb24xMSgnUzAxMDA0NDA5L1MwMTAxMTE3NCcpCmBgYAogIAphIDwtIGFycmFuc2ltZCAlPiUKbXV0YXRlKAogICAgbG9uID0gbWFwX2RibChnZW9tZXRyeSwgfnN0X2NlbnRyb2lkKC54KVtbMV1dKSwKICAgIGxhdCA9IG1hcF9kYmwoZ2VvbWV0cnksIH5zdF9jZW50cm9pZCgueClbWzJdXSkKICAgICkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBQZXJjZW50aWxlKSkgKwogIGZhY2V0X3dyYXAobGlzdElEIH4geWVhcikgKwogIHRoZW1lX2dyZXkoKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFBlcmNlbnRpbGUsIHggPSBsb24sIHkgPSBsYXQpLCBzaXplID0gMiwgY29sb3VyID0gIndoaXRlIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICAKCmIgPC0gYXJyYW5zaW1kICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGRhdGEgPSBhcnJhbnN1YnNlY3QpICsKICB0aGVtZV9ncmV5KCkgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBEYXRhWm9uZSkpCgoKYyA8LSBhcnJhbnNpbWQgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoKSArCiAgdGhlbWVfZ3JleSgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIobmV3YXJyYW5jb29yZGluYXRlcywgbGlzdElEID09IGFyZ3VtZW50KSwgCiAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIHNpemU9MSkgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gZmlsdGVyKG5ld2FycmFuY29vcmRpbmF0ZXMsIGxpc3RJRCA9PSBhcmd1bWVudCksIAogICAgICAgICAgICBhZXMobGFiZWwgPSBmaWx0ZXIobmV3YXJyYW5jb29yZGluYXRlcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0SUQgPT0gYXJndW1lbnQpJHBvc3Rjb2RlLCAKICAgICAgICAgICAgICAgIHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIHNpemU9MikgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpICsKICBjb29yZF9zZihjcnM9IDQzMjYsIGRhdHVtID0gc2Y6OnN0X2Nycyg0MzI2KSkKCmdyaWQuYXJyYW5nZShhLCBiLCBjLCBucm93ID0gMSkKCg==